package cn.kgc.spring.proxy.jdk;

import cn.kgc.spring.entity.User;
import cn.kgc.spring.service.UserService;
import cn.kgc.spring.service.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author: mosin
 * @version: v1.0  2022/10/13
 * 基于jdk动态代理
 * spring AOP
 *  通知： 额外增强的业务
 *          1.前置通知
 *          2.后置通知
 *          3.异常通知
 *          4.环绕通知
 *          5.最终通知
 *  切点： 将通知添加到哪个类的哪个方法上
 *  切面： 通知+切点
 *
 */
public class JDKProxy {

    public static void main(String[] args) {

        UserService userService = new UserServiceImpl();

        /**
         * 通过jdk的动态代理技术生成被代理对象的代理对象
         * ClassLoader loader   类加载器  代理配不会被分配类加载器 执行时需要借助外部的类加载器
         * Class<?>[] interfaces    被代理对象实现接口的数组    代理对象要和被代理对象实现相同的接口
         * InvocationHandler        增强业务对象
         */
        ClassLoader loader =  JDKProxy.class.getClassLoader();
        Class[] interfaces  = {UserService.class};
        UserService o = (UserService) Proxy.newProxyInstance(loader, interfaces, new InvocationHandler() {

            // 通过代理对象调用被代理对象中的方法时  首先进入 被代理对象的invoke方法

            /*
             * @param proxy   代理对象  忽略
             * @param method   通过代理对象调用的方法  会以Method对象的方式传入invoke
             * @param args     代理对象调用方法的参数   Object[] args
             * @return    Object   调用方法的返回值
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                //System.out.println("==========进入invoke方法==========");
                //System.out.println("method name = "+method.getName());


                try {
                    System.out.println("---------开启事务-----------");

                    //通过反射调用方法
                    Object invoke = method.invoke(userService, args);

                    System.out.println("---------提交事务-----------");

                    return invoke;
                } catch (Exception e) {
                    System.out.println("---------回滚事务-----------");
                    e.printStackTrace();
                }

                //System.out.println("--------参数列表--------");
                //for (Object arg : args) {
                //    System.out.println("arg = " + arg);
                //}
                //增强的业务
                return null;
            }
        });
        // 打印输出代理对象
        System.out.println(o.getClass());

        //o.delete(10);

        User user = new User();
        user.setName("tom");
        user.setId(20);

        Integer add = o.add(user);
        System.out.println(add);


    }
}
